﻿#ifndef _EASY_TCP_CLIENT_CLASS_HPP_
#define _EASY_TCP_CLIENT_CLASS_HPP_

#if defined(_MSC_VER) /*&& defined(_WIN32) && defined(WIN32)*/
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
// SDL 关闭了也可以 除去 4996 的警告（错误）
#pragma warning(disable:4996) // #define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <WinSock2.h>

#include <Ws2tcpip.h>
#pragma comment(lib, "ws2_32")
//#include <sockhelper.h>
#else
#ifndef SOCKET_DEFINED
#define SOCKET_DEFINED
typedef int SOCKET;
#endif // !SOCKET_DEFINED

#ifndef INVALID_SOCKET
#define INVALID_SOCKET  (SOCKET)(~0)
#endif
#ifndef SOCKET_ERROR
#define SOCKET_ERROR            (-1)
#endif
//#elif defined(unix) || defined(__unix) || defined(__unix__)
////#warning You are using UNIX
//#elif defined(__APPLE__) || defined(__MACH__)
////#warning You are using Mac OS X
//#elif defined(__linux__)
////#warning You are using Linux
//#elif defined(__FreeBSD__)
////#warning You are using FreeBSD
//#else
//#error Unknown OS
#endif

#include <stdio.h>


#include <netmsgdef.h>

// 实例对象...[
#include <textmessage.h>

// 实例对象...]

#include <MyOutputDebugInfo.h>


class EasyTcpClient {

    SOCKET _sock;
public:
    EasyTcpClient() {
        _sock = INVALID_SOCKET;
    }

    virtual ~EasyTcpClient(){
        close();
    }

    static int LoadSocket(){
#if defined(_WIN32)
        WORD wVer = MAKEWORD(2, 2);
        WSADATA data;
        WSAStartup(wVer, &data);
#endif
        return 0;
    }

    static int UnloadSocket(){
#if defined(_WIN32) && defined(WIN32) && defined(_MSC_VER)
        WSACleanup();
#endif
        return 0;
    }
    // ---------------------------------------------------------------------


    int InitSocket(){
        int retval = -1;
        do
        {
            if (INVALID_SOCKET == _sock)
                this->close();

            _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            if (INVALID_SOCKET == _sock) {
                printf("socket函数调用失败\n");
                break;
            }
            retval = 0;
        } while (false);
        return retval;
    }

    int connectTo(const char *ip, unsigned short port){
        int retVal = -1;

        do
        {
            sockaddr_in _sin;
            _sin.sin_family = AF_INET;
            _sin.sin_port = htons(port);
            _sin.sin_addr.S_un.S_addr = inet_addr(ip);
            retVal = connect(_sock, (sockaddr*)&_sin, sizeof(sockaddr_in));
            if (SOCKET_ERROR == retVal) {
                printf("connect 失败\n");
                break;
            }
            printf("连接服务器成功!\n");


            //在connect之后，设置读和写的超时时间

            //    STR_TIME lstr_timevalue;
            //int li_len;

            //li_len = sizeof(lstr_timevalue);
            //lstr_timevalue.tv_sec = 2;  //设置超时时间为2秒
            //setsockopt(li_sockfd, SOL_SOCKET, SO_RCVTIMEO, (void *)&lstr_timevalue, li_len);
            //setsockopt(li_sockfd, SOL_SOCKET, SO_SNDTIMEO, (void *)&lstr_timevalue, li_len);

            retVal = 0;
        } while (false);

        return retVal;
    }

    void close(){
        if (INVALID_SOCKET != _sock)
        {
#if 0
            shutdown(_sock, SD_RECEIVE);
            shutdown(_sock, SD_SEND);
#else
            shutdown(_sock, SD_BOTH);
#endif
            
#ifdef _WIN32
            closesocket(_sock);
#else
            close(_sock);
#endif
        }
        _sock = INVALID_SOCKET;
    }

    bool isRunning()
    {
        bool suc = (INVALID_SOCKET != _sock);
        return suc;
    }

    void onRun()
    {
        do
        {
            fd_set fdRead;
            FD_ZERO(&fdRead);
            FD_SET(_sock, &fdRead);
            timeval t = { 0, 550 };
            int ret = select(0, &fdRead, NULL, NULL, &t);
            if (ret < 0) {
                printf("select失败，任务结束.\n");
                break;
            }

            if (FD_ISSET(_sock, &fdRead))
            {
                FD_CLR(_sock, &fdRead);

                ret = onRecv();
                if (ret < 0)
                {
                    break;
                }
            }

            //printf("空闲时间处理其他业务.\n");
        } while (false);
    }

    int onRecv()
    {
        int nret = 0;
        char msgBuf[256];

        do
        {
            nret = recv(_sock, msgBuf, sizeof(msgBuf), 0);
            if (nret <= 0) {
                if (0 == nret) {
                    printf("远程socket 已关闭\n");
                    nret = -1;
                }
                else {
                    printf("recv 失败\n");
                    nret = -2;
                }
                break;
            }

            // 注意，recv 返回的长度可能小于传递的需要接收的长度
            printf("已接收 %d 字节： %s\n", nret, msgBuf);
            nret = 0;
        } while (false);
        return nret;
    }

    int sendData(char* data, int dataLen)
    {
        int nret = send(_sock, (char*)data, dataLen, 0);
        return nret;
    }

private:
};



#ifndef myprintf_defined
#define myprintf_defined
#define myprintf(fmt, ...) \
    Output::OutputDebugPrintf2("[< %s >] " fmt, __FUNCTION__, ##__VA_ARGS__)
#endif

#endif // end of file
